/**
 * 
 */
package commons.base.netty.http;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.MixedAttribute;
import io.netty.util.CharsetUtil;

/**
 * @author yuan<cihang.yuan@happyelements.com>
 * @since 1.7
 */
public abstract class NettyHttpServlet {

	private static final Logger log = LogManager.getLogger(NettyHttpServlet.class);
	
	public abstract void init()throws Exception;
	
	public void processRequest(FullHttpRequest request, NettyHttpResponse response){
		Map<String, String> params = new HashMap<String, String>();
		
		if (request.method() == HttpMethod.POST) {
			// 解析POST请求
			try {
				parsePostRequest(request, params);
			} catch (Throwable e) {
				log.error("[NettyHttpServlet]" + e.getMessage(), e);
				return ;
			}
		}else if(request.method() == HttpMethod.GET){
			// 解析GET请求
			try {
				parseGetRequest(request, params);
			} catch (Throwable e) {
				log.error("[NettyHttpServlet]" + e.getMessage(), e);
				return ;
			}
		}else{
			// 不支持其他类型请求
			return ;
		}
		
		// 业务处理
		try {
			Object result = doService(params);
			response.renderJson(result);
		} catch (Throwable e) {
			log.error("[NettyHttpServlet][doService]" + e.getMessage(), e);
			response.render500(e.getMessage());
			return ;
		}
	}
	
	private void parsePostRequest(FullHttpRequest req, Map<String, String> postParams) throws IOException {
		HttpPostRequestDecoder postdeDecoder = null;
		try {
			// post decoder
			postdeDecoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(), req, CharsetUtil.UTF_8);
			postdeDecoder.offer(req);
			List<InterfaceHttpData> dataList = postdeDecoder.getBodyHttpDatas();

			for (InterfaceHttpData data : dataList) {
				// <name,value>
				String name = data.getName();

				if (InterfaceHttpData.HttpDataType.Attribute == data.getHttpDataType()) {
					MixedAttribute attribute = (MixedAttribute) data;
					attribute.setCharset(CharsetUtil.UTF_8);

					String value = attribute.getValue();

					// 放入参数列表
					postParams.put(name, value);
				}
			}
		} finally {
			if (postdeDecoder != null) {
				postdeDecoder.destroy();
			}
		}
	}
	
	private void parseGetRequest(FullHttpRequest req, Map<String, String> getParams) {
		QueryStringDecoder decoderQuery = new QueryStringDecoder(req.uri());
		
		Map<String, List<String>> map = decoderQuery.parameters();
		for(String name : map.keySet()){
			List<String> value = map.get(name);
			if((value == null) || (value.isEmpty())){
				getParams.put(name, null);
			}else{
				getParams.put(name, value.get(0));
			}
		}
	}
	
	protected Object doService(Map<String, String> params)throws Exception{
		return null;
	}
	
	public abstract void destroy();
	
}
